import os
from copy import deepcopy
from typing import Dict

import numpy as np
import pandas as pd
import plotly.graph_objects as go

from utils import get_code_market_data


def calculate_year_result(df: pd.DataFrame, col: str) -> Dict:
    """
    :param df: 包含date_time和col的表格
    :param col: 作为价值序列计算的列
    :return:
    """
    dftrade = deepcopy(df)
    dftrade.sort_values("date_time", inplace=True)
    dfbase_profit = dftrade.iloc[0][col]
    dflast_profit = dftrade.iloc[-1][col]
    start = dftrade.iloc[0]["date_time"]
    end = dftrade.iloc[-1]["date_time"]
    return_value = (dflast_profit - dfbase_profit) / dfbase_profit
    annual_return = (1 + return_value) ** (252 / len(dftrade)) - 1

    dftrade["norm_cash"] = dftrade[col] / dfbase_profit
    dftrade["delta_cash"] = (dftrade[col] - dftrade[col].shift(1)) / dftrade[col].shift(
        1
    )
    dftrade["peak"] = np.maximum.accumulate(dftrade["norm_cash"])
    dftrade["drawdown"] = (dftrade["norm_cash"] - dftrade["peak"]) / dftrade["peak"]
    max_drawdown = dftrade["drawdown"].min()

    fix_profit = 0.04
    fix_profit_day = (1 + fix_profit) ** (1 / 252) - 1
    dftrade["delta_abs"] = dftrade["delta_cash"] - fix_profit_day

    sharp_day = dftrade["delta_abs"].mean() / dftrade["delta_abs"].std()

    info = {
        "起始日期": start,
        "终止日期": end,
        "收益率": return_value,
        "年化收益率": annual_return,
        "最大回撤": max_drawdown,
        "日收益率夏普值": sharp_day,
    }

    return info


def calculate_backtrade_result(profit_file: str):
    basedir = os.path.dirname(profit_file)
    dftrade = pd.read_csv(profit_file, index_col=0)
    dftrade["date_time"] = dftrade["datetime"].apply(lambda x: x[:4] + x[5:7] + x[8:10])
    dftrade.drop("datetime", inplace=True, axis=1)
    dftrade.sort_values("date_time", inplace=True)
    dfbase_profit = dftrade.iloc[0]["cash"]
    dftrade["norm_cash"] = dftrade["cash"] / dfbase_profit
    dftrade["delta_cash"] = (dftrade["cash"] - dftrade["cash"].shift(1)) / dftrade[
        "cash"
    ].shift(1)

    start_date = dftrade["date_time"].min()
    end_date = dftrade["date_time"].max()
    df300 = get_code_market_data(
        "000300.SH", start_date, end_date, period="1d", dividend_type="front_ratio"
    )
    df300.reset_index(names=["date_time"], inplace=True)
    df300["date_time"] = df300["date_time"].apply(lambda x: str(x))
    df300.sort_values("date_time", inplace=True)
    df300base = df300.iloc[0]["close"]
    df300["norm_close"] = df300["close"] / df300base
    df300["delta_close"] = (df300["close"] - df300["close"].shift(1)) / df300[
        "close"
    ].shift(1)

    df = pd.merge(dftrade, df300, on=["date_time"])

    df["norm_cmp"] = df["norm_cash"] / df["norm_close"]

    df["year"] = df["date_time"].apply(lambda x: x[:4])

    allinfo = []
    for year, subdf in df.groupby("year"):  # 计算每一年的指标数据
        subinfo_st = calculate_year_result(subdf, "cash")
        subinfo_st["name"] = "strategy"
        subinfo_base = calculate_year_result(subdf, "close")
        subinfo_base["name"] = "base"
        allinfo.append(subinfo_st)
        allinfo.append(subinfo_base)

    dfinfo = pd.DataFrame(allinfo)

    dfinfo.to_csv(os.path.join(basedir, "analyze_info.csv"))

    fig = go.Figure()

    fig.add_trace(
        go.Scatter(
            x=df["date_time"],
            y=df["norm_cash"],
            name="策略净值",
            yaxis="y1",
            mode="lines",
        )
    )

    fig.add_trace(
        go.Scatter(
            x=df["date_time"],
            y=df["norm_close"],
            name="沪深300净值",
            yaxis="y1",
            mode="lines",
        )
    )

    fig.add_trace(
        go.Scatter(
            x=df["date_time"],
            y=df["norm_cmp"],
            name="策略相对净值",
            yaxis="y1",
            mode="lines",
        )
    )

    fig.add_trace(
        go.Bar(x=df["date_time"], y=df["delta_cash"], name="策略增长率", yaxis="y2")
    )

    fig.add_trace(
        go.Bar(x=df["date_time"], y=df["delta_close"], name="沪深300增长率", yaxis="y2")
    )

    fig.update_layout(
        title="策略和基准对比图",
        xaxis_title="日期",
        yaxis_title="净值",
        xaxis_type="category",
        xaxis_rangeslider_visible=True,
        height=1000,
        yaxis2=dict(
            title="增长率",
            overlaying="y",
            side="right",
            fixedrange=False,
            zeroline=True,  # 显示x轴的0轴线
            zerolinewidth=2,  # 设置0轴线宽度
            zerolinecolor="gray",
        ),
        yaxis=dict(fixedrange=False),
    )
    fig.write_html(os.path.join(basedir, "analyze_profit_cmp.html"))


if __name__ == "__main__":
    import sys

    profit_file = sys.argv[1]
    calculate_backtrade_result(profit_file)
